package cn.xiaolang.thread.threadlocal;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * 父子线程传值(通过InheritableThreadLocal实现)
 * <p>
 * 虽然InheritableThreadLocal可以解决在子线程中获取父线程的值的问题，
 * 但是在使用线程池的情况下，由于不同的任务有可能是同一个线程处理，
 * 因此这些任务取到的值有可能并不是父线程设置的值
 * </p>
 *
 * @author Dean
 * @date 2021-01-20
 */
@Slf4j
public class ParentChildPassValueIssueSolve2 {

    private static final ThreadLocal<TargetUser> threadLocal = new InheritableThreadLocal<>();

    /**
     * 在执行start方法前获取到父线程的值，
     * 因为在thread对象执行start方法前，
     * 当前线程还是父线程，因此可以通过threadLocal.get方法获取父线程的值
     */
    @SuppressWarnings("uncheck")
    public static void main(String[] args) throws InterruptedException {
        //主线程设置一个值
        threadLocal.set(new TargetUser("dean-parent"));

        //运行子线程
        Thread childThread = new Thread(new ChildThread(), "child-thread");
        childThread.start();

        //主线成等待子线程运行完，以便观察主线中设置的值是否被子线程成功修改
        childThread.join();

        log.info(" parent thread get result:{}", threadLocal.get());
        threadLocal.remove();

    }

    static class ChildThread implements Runnable {

        @Override
        public void run() {

            //如果启用了线程（调用start方法），调用get方法是获取不到值的
            TargetUser originVal = threadLocal.get();
            log.info("child get from parent directly:{}", originVal);

            // 修改从父线程获取到的值
            originVal.setName("dean-child");
        }
    }

    @Data
    @AllArgsConstructor
    private static class TargetUser {

        private String name;

    }

}


